import pickle
from typing import Tuple, List
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider
import re


def check_broken_fix_test(result_tests):
    res_broken_test = []
    res_fixed_test = []
    if not isinstance(result_tests, List):
        return [False], [False]
    for i in range(0, len(result_tests) - 1):
        if result_tests[i][1] and not result_tests[i+1][1]:
            res_broken_test.append(result_tests[i+1][0])
        elif not result_tests[i][1] and result_tests[i+1][1]:
            res_fixed_test.append(result_tests[i+1][0])
    if not res_broken_test and not res_fixed_test:
        res_fixed_test = [result_tests[0][1]]
        res_broken_test = [result_tests[0][1]]
    return res_broken_test, res_fixed_test


def sorted_result(name_list: List):
    result_numbers = []
    if not isinstance(name_list, List):
        return []
    for i in name_list:
        if re.match(r'^\d', i[0]):
            result_numbers.append(i)
    name_list = [i for i in name_list if i not in result_numbers]
    sorted_list = sorted(name_list, key=lambda x: int(x[0].split()[0].split('_')[1]))
    result_numbers.sort()
    sorted_list.extend(result_numbers)
    return sorted_list


def identify_broken_test(result_test):
    if not isinstance(result_test, List):
        return 'Некорректные данные'
    if not result_test:
        return ''
    for i in range(len(result_test) - 1, 0, -1):
        if isinstance(result_test[i], Tuple):
            if result_test[i][1]:
                return 'тест работает'
            elif not result_test[i][1] and result_test[i-1][1]:
                return result_test[i][0].split()[0].split("_")[1] if result_test[i][0].startswith('rev')\
                    else result_test[i][0].split()[0].split("_")[2]
        else:
            return 'Некорректные данные'

    return "тест сломан на протяжении всего данного периода"


def check_test_result(name_test, test_list):
    res_id = []
    if not isinstance(test_list, List):
        return []
    for i_test in test_list:
        if "full_check" in i_test.name:
            find = False
            for test in i_test.testsuites:
                for test_case in test.testsuite:
                    if test_case.name == name_test:
                        if test_case.time < 0:
                            res_id.append((i_test.name, None))
                        else:
                            res_id.append((i_test.name, True if test_case.result == "OK" else False))
                        find = True
                        break
                if find:
                    break
    return sorted_result(res_id)


def check_test_time(name_test, test_list):
    time_id = []
    if not isinstance(test_list, List):
        return []
    for i_test in test_list:
        if "full_check" in i_test.name:
            find = False
            for test in i_test.testsuites:
                for test_case in test.testsuite:
                    if test_case.name == name_test:
                        time_id.append((i_test.name, test_case.time if test_case.time >= 0 else -100))
                        find = True
                        break
                if find:
                    break
    return sorted_result(time_id)


def zip_name_time_result(res_id, time_id):
    pass


def now_result_test(name_test, test_result):
    with open('broken_test.txt', 'a', encoding='utf-8') as file:
        info = identify_broken_test(test_result)
        file.write(f'Информация о тесте {name_test}: {info}\n')


def id_name(name_list):
    return [name_list[i][0] for i in range(len(name_list))]


class CreatingPlotNameTime:

    def __init__(self, x_y_ax, name_test):
        self.fig, ax = None, None
        self.x = [i[0] for i in x_y_ax]
        self.y = [i[1] for i in x_y_ax]
        self.id_name = [str(i + 1) for i in range(len(x_y_ax))]
        self.color = []
        self.name_test = name_test

    def add_color(self, colors):
        for condition in colors:
            if condition[1] is None:
                self.color.append('grey')
            elif condition[1]:
                self.color.append('green')
            else:
                self.color.append('red')

    def set_interval(self, left=0, right=1, last=None, vicinit=15, broken_name=None):
        if broken_name:

            pattern = rf"_{broken_name}\b"
            broken_test = [self.x.index(i) for i in self.x if re.search(pattern, i)]
            if broken_test:
                self.x = self.x[broken_test[0] - vicinit:broken_test[0]+vicinit]
                self.y = self.y[broken_test[0] - vicinit:broken_test[0]+vicinit]
                self.id_name = self.id_name[broken_test[0] - vicinit:broken_test[0]+vicinit]
                if self.color:
                    self.color = self.color[broken_test[0] - vicinit:broken_test[0]+vicinit]
        if left and right > 1:
            self.id_name = self.id_name[left:right]
            self.x = self.x[left:right]
            self.y = self.y[left:right]
            if self.color:
                self.color = self.color[left:right]
        if last:
            self.id_name = self.id_name[-last:]
            self.x = self.x[-last:]
            self.y = self.y[-last:]
            if self.color:
                self.color = self.color[-last:]


    def slidebar(self, pos):
        self.ax.set_xlim(pos, pos + 75)
        self.fig.canvas.draw_idle()

    def check_text_exists(self, x, y, text):
        texts = self.fig.texts  # Получаем список всех текстовых объектов на фигуре
        for t in texts:
            if abs(t.get_position().x0 - x) < 0.01 and abs(t.get_position().y0 - y) < 0.01 and t.get_text() == text:
                return True
        return False

    def on_hover(self, event):
        xdata, ydata = event.xdata, event.ydata

        # Определяем, какой столбец был выбран
        selected_bar = None
        for i, bar in enumerate(self.bars):
            if xdata >= bar.get_x() and xdata <= bar.get_x() + bar.get_width():
                selected_bar = i
                break
        if selected_bar is not None:
            # Отображаем информацию о выбранном баре
            print(f"{self.x[selected_bar]}")

    def show(self):
        self.fig, self.ax = plt.subplots()
        plt.subplots_adjust(bottom=0.1)
        plt.figtext(0.02, 0.9, self.name_test, fontsize=14)

        for tick in self.ax.get_xticklabels():
            tick.set_rotation(90)
        if self.color:
            self.bars = self.ax.bar(np.array(self.id_name), np.array(self.y), color=self.color)
        else:
            self.bars = self.ax.bar(np.array(self.id_name), np.array(self.y))

        slidebarpos = plt.axes([0.1, 0.001, 0.5, 0.03])
        slider = Slider(slidebarpos, '', 0, valmax=len(self.x) - 75, valinit=0)
        slider.on_changed(self.slidebar)
        self.fig.canvas.mpl_connect('button_press_event', self.on_hover)
        plt.show()



def info_tests(json_list):

    # names = ['Cross', 'Ring', 'Fractal', 'sketch_2', 'nanosoft_g2_connection_lseg_spline_2',
    #           'kompas_28094_not_overdefined_case', 'KOMPAS_32620', 'tancc_01', 'ang3d', 'kompas_59202', 'pft_resolve']
    names = ['Ring']
    for name in names:
        x_y = check_test_time(name, json_list)
        test_result = check_test_result(name, json_list)
        if x_y:
            plotting(x_y, name, test_result)
        now_result_test(name, test_result)


def plotting(x_y, name, test_result):
    graph = CreatingPlotNameTime(x_y, name)
    graph.add_color(test_result)
    graph.set_interval(broken_name='113616')
    graph.show()


def unpact_class_list():
    with open('class_list.pkl', 'rb') as f:
        return pickle.load(f)


if __name__ == "__main__":
    loaded_obj = unpact_class_list()
    info_tests(loaded_obj)



